package com.github.hgkmail.hello.cmd.helper;

import com.thoughtworks.qdox.JavaProjectBuilder;
import com.thoughtworks.qdox.model.JavaClass;
import com.thoughtworks.qdox.model.JavaField;
import com.thoughtworks.qdox.model.JavaMethod;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import java.io.File;
import java.io.StringWriter;
import java.util.List;

/**
 * 解析 Java 类源文件
 *
 * @author kimhuang
 * @date 2021/2/12
 */
public abstract class BaseParseClass {

    /**
     * 执行解析
     */
    public void run() {
        parseClass(new YourParseClassListener());
    }

    /**
     * 遍历class的元素
     * @param listener 遍历事件监听器
     */
    protected void parseClass(ParseClassListener listener) {
        JavaProjectBuilder projectBuilder = new JavaProjectBuilder();
        projectBuilder.addSourceTree(new File(ParseClassConfig.SOURCE_DIR));
        JavaClass targetClass = projectBuilder.getClassByName(ParseClassConfig.TARGET_CLASS);

        // class begin
        listener.onStart(targetClass);
        // fields
        List<JavaField> fields = targetClass.getFields();
        for (JavaField field:fields) {
            listener.onField(targetClass, field);
        }
        // methods
        List<JavaMethod> methods = targetClass.getMethods();
        for (JavaMethod method:methods) {
            listener.onMethod(targetClass, method);
        }
        // class end
        listener.onEnd(targetClass);
    }

    /**
     * 打印生成结果
     * @param templatePath velocity模板地址
     */
    protected void renderVm(String templatePath, RenderListener rListener) {
        VelocityEngine ve = new VelocityEngine();
        ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        ve.init();

        Template t = ve.getTemplate(templatePath);
        VelocityContext vContext = new VelocityContext();
        //set var
        rListener.beforeRender(vContext);

        StringWriter sw = new StringWriter();
        t.merge(vContext, sw);
        //get result
        rListener.afterRender(vContext, sw.toString());
    }

    /**
     * 定义你自己的监听器
     */
    class YourParseClassListener implements ParseClassListener {
        //定义元信息变量

        @Override
        public void onStart(JavaClass jClass) {
            //收集class信息
        }

        @Override
        public void onField(JavaClass jClass, JavaField jField) {
            //收集field信息
        }

        @Override
        public void onMethod(JavaClass jClass, JavaMethod jMethod) {
            //收集method信息
        }

        @Override
        public void onEnd(JavaClass jClass) {
            //输出渲染结果
        }

    }

}
